package io.github.soiff.mdoc.settings;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import io.github.soiff.mdoc.utils.Parser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * Created by z0228 on 2016/10/22.
 * An implementation for configure processor.
 *
 * @author : z0228
 * @version : 1.0
 * @since : 1.8
 */
@SuppressWarnings({"WeakerAccess", "unused"})
@JsonIgnoreProperties(ignoreUnknown = true)
public class Settings implements Serializable {
    private static final long serialVersionUID = 0L;
    private static final Logger log = LoggerFactory.getLogger(Settings.class);

    public static final Settings DEFAULT = new Settings();

    private static final Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
    private static final Map<String, Template> templates = new HashMap<>(32);

    static {
        cfg.setDefaultEncoding("utf-8");
        cfg.setBooleanFormat("yes,no");
    }

    /**
     * -Dconfiguration=`configuraiton`
     */
    private String configuration;
    /**
     * Annotation and the Freemaker template.
     */
    private Map<String, String> annotations = Collections.emptyMap();
    /**
     * Default extension for generated documents.
     */
    private String extension = "md";
    /**
     * Default output directory for generated documents.
     */
    private String directory = null;
    /**
     * Default folder to find freemaker templates.
     */
    private String root = null;

    private String author = null;
    private Date date = new Date();

    public Settings() {
    }

    public Template getTemplate(String annotation) {
        if (! templates.containsKey(annotation)) {
            final String value = annotations.get(annotation);
            File config = new File(value);
            Template template;
            try {
                if (config.exists())
                    template = new Template(annotation, new FileReader(config), cfg);
                else {
                    config = new File(new File(configuration).getParent(), value);
                    if (config.exists())
                        template = new Template(annotation, new FileReader(config), cfg);
                    else
                        template = new Template(annotation, new StringReader(value), cfg);
                }
                templates.put(annotation, template);
            } catch (IOException e) {
                log.error("Failed to load template of '{}' for {}", annotation, e.getCause());
                templates.put(annotation, null);
            }
        }
        return templates.get(annotation);
    }

    public String getConfiguration() {
        return configuration;}

    public void setConfiguration(String configuration) {
        this.configuration = configuration;
    }

    public Map<String, String> getAnnotations() {
        return annotations;
    }

    public void setAnnotations(Map<String, String> annotations) {
        this.annotations = annotations;
    }

    public String getExtension() {
        return extension;
    }

    public void setExtension(String extension) {
        this.extension = extension;
    }

    public String getDirectory() {
        return directory;
    }

    public void setDirectory(String directory) {
        this.directory = directory;
    }

    public String getRoot() {
        return root;
    }

    public void setRoot(String root) {
        this.root = root;
        cfg.setTemplateLoader(new ClassTemplateLoader(Parser.class, root));
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}
